package cn.edu.cug.cs.gtl.oi.inventor.demo;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

import javax.swing.JFileChooser;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.filechooser.FileFilter;

import cn.edu.cug.cs.gtl.oi.utils.Example;
import cn.edu.cug.cs.gtl.oi.utils.ViewerComponentsFactory;
import cn.edu.cug.cs.gtl.oi.utils.editors.ColorEditor;
import cn.edu.cug.cs.gtl.oi.utils.editors.DirectionalLightEditor;
import com.openinventor.inventor.SbColor;
import com.openinventor.inventor.SoDB;
import com.openinventor.inventor.SoInput;
import com.openinventor.inventor.SoPath;
import com.openinventor.inventor.SoPreferences;
import com.openinventor.inventor.actions.SoSearchAction;
import com.openinventor.inventor.nodes.SoDirectionalLight;
import com.openinventor.inventor.nodes.SoGradientBackground;
import com.openinventor.inventor.nodes.SoNode;
import com.openinventor.inventor.nodes.SoSeparator;
import com.openinventor.inventor.viewercomponents.awt.IViewerExaminer;
import com.openinventor.inventor.viewercomponents.nodes.SceneExaminer;

/**
 * SceneViewer allows to visualize scene graphs.
 */
public class SceneViewer extends Example
{

    private DirectionalLightEditor headlightEditor;
    private ColorEditor colorEditor;
    private SoGradientBackground m_background;
    private IViewerExaminer m_viewer;

    public static void main(String[] argv)
    {
        SceneViewer example = new SceneViewer();
        example.demoMain("Scene Viewer");
    }

    @Override
    public void start()
    {
        setLayout(new BorderLayout());

        JMenuBar menubar = buildMenu();
        add(menubar, BorderLayout.NORTH);

        m_viewer = ViewerComponentsFactory.createViewerExaminer();
        SceneExaminer root = m_viewer.getRenderArea().getSceneInteractor();

        headlightEditor = new DirectionalLightEditor();

        // Get headlight
        SoSearchAction searchAction = new SoSearchAction();
        searchAction.setNodeClass(SoDirectionalLight.class);
        searchAction.apply(root);
        SoPath path = searchAction.getPath();
        if ( path == null )
        {
            System.err.println("Headlight not found");
        }
        else
        {
            headlightEditor.attach(path);
        }

        // Insert a background
        SbColor color = new SbColor(Color.BLACK);
        m_background = new SoGradientBackground();
        m_background.color0.setValue(color);
        m_background.color1.setValue(color);
        root.insertChild(m_background, 0);

        colorEditor = new ColorEditor();
        colorEditor.setColor(color);
        colorEditor.addListener(new ColorEditorListener());

        SoNode sceneGraph = readSceneGraph("$OIVJHOME/data/models/spongetri4.iv");

        m_viewer.setSceneGraph(sceneGraph);
        m_viewer.viewAll();

        final Component component = m_viewer.getComponent();
        component.setPreferredSize(new java.awt.Dimension(600, 500));
        add(component, BorderLayout.CENTER);
    }

    @Override
    public void stop()
    {
        colorEditor.setVisible(false);
        colorEditor.dispose();
        headlightEditor.setVisible(false);
        headlightEditor.dispose();
        m_viewer.dispose();
    }

    private JMenuBar buildMenu()
    {
        JPopupMenu.setDefaultLightWeightPopupEnabled(false);

        // File menu
        JMenu fileMenu = new JMenu("File");

        final FileFilter ivFileFilter = new FileFilter()
        {

            @Override
            public String getDescription()
            {
                return "Open-Inventor files";
            }

            @Override
            public boolean accept(File f)
            {
                if ( f == null )
                    return false;
                if ( f.isDirectory() )
                    return true;
                return f.getName().toLowerCase().endsWith(".iv");
            }
        };

        final JFileChooser ivFileChooser = new JFileChooser(
                new File(SoPreferences.getValue("OIVJHOME") + File.separator + "data" + File.separator + "models"));
        ivFileChooser.setFileFilter(ivFileFilter);
        ivFileChooser.removeChoosableFileFilter(ivFileChooser.getAcceptAllFileFilter());

        JMenuItem openIvFileItem = new JMenuItem("Open");

        openIvFileItem.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                if ( ivFileChooser.showOpenDialog(null) != JFileChooser.APPROVE_OPTION )
                    return;
                String fileName = ivFileChooser.getSelectedFile().getAbsolutePath();
                SoNode node = readSceneGraph(fileName);
                m_viewer.setSceneGraph(node);
                m_viewer.viewAll();
            }
        });

        fileMenu.add(openIvFileItem);

        JMenuItem closeDemoItem = new JMenuItem("Exit");
        closeDemoItem.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                System.exit(0);
            }
        });
        fileMenu.add(closeDemoItem);

        // Editor menu
        JMenuItem backColorItem = new JMenuItem("Background color...");
        backColorItem.addActionListener(new ChangeColor());

        JMenuItem editLightItem = new JMenuItem("Headlight editor...");
        editLightItem.addActionListener(new EditLight());

        JMenu editorsMenu = new JMenu("Editors");
        editorsMenu.add(backColorItem);
        editorsMenu.add(editLightItem);

        JMenuBar menubar = new JMenuBar();
        menubar.add(fileMenu);
        menubar.add(editorsMenu);
        return menubar;
    }

    private static SoNode readSceneGraph(String fileName)
    {
        SoInput input = new SoInput();

        if ( !input.openFile(fileName) )
        {
            System.err.println("Cannot open file " + fileName);
            return null;
        }

        SoSeparator node = SoDB.readAll(input);
        if ( node == null )
        {
            System.err.println("Problem reading file");
            input.closeFile();
            return null;
        }

        input.closeFile();
        return node;
    }

    //////////////////////////////////////////////////////////////////////
    // inner classes : listeners
    //////////////////////////////////////////////////////////////////////

    class ChangeColor implements ActionListener
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            colorEditor.pack();
            colorEditor.setVisible(true);
        }
    }

    class EditLight implements ActionListener
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            headlightEditor.pack();
            headlightEditor.setVisible(true);
        }
    }

    class ColorEditorListener extends ColorEditor.Listener
    {
        @Override
        public void valueChanged(SbColor newColor)
        {
            m_background.color0.setValue(newColor);
            m_background.color1.setValue(newColor);
        }
    }

}
